home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 10081 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  33.5 KB

  1. Path: sun.soe.clarkson.edu!cline
  2. From: cline@sun.soe.clarkson.edu (Marshall Cline)
  3. Newsgroups: comp.lang.c++
  4. Subject: C++ FAQ: posting #3/4
  5. Followup-To: comp.lang.c++
  6. Date: 6 Mar 1996 02:21:30 GMT
  7. Organization: Paradigm Shift, Inc (technology consulting)
  8. Sender: cline@sun.soe.clarkson.edu
  9. Distribution: world
  10. Expires: +1 month
  11. Message-ID: <4hisra$hfl@library.erc.clarkson.edu>
  12. Reply-To: cline@parashift.com (Marshall Cline)
  13. NNTP-Posting-Host: sun.soe.clarkson.edu
  14. Summary: Please read this before posting to comp.lang.c++
  15. Archive-name: C++-faq/part3_4
  16.  
  17. comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
  18. Copyright (C) 1991-96 Marshall P. Cline, Ph.D.
  19. Posting 3 of 4.
  20. Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc
  21.  
  22. ==============================================================================
  23. SECTION 14: Style guidelines
  24. ==============================================================================
  25.  
  26. Q87: What are some good C++ coding standards?
  27.  
  28. Thank you for reading this answer rather than just trying to set your own
  29. coding standards.
  30.  
  31. But beware that some people on comp.lang.c++ are very sensitive on this issue.
  32. Nearly every software engineer has, at some point, been exploited by someone
  33. who used coding standards as a "power play."  Furthermore some attempts to set
  34. C++ coding standards have been made by those who didn't know what they were
  35. talking about, so the standards end up being based on what WAS the
  36. state-of-the-art when the standards setters where writing code.  Such
  37. impositions generate an attitude of mistrust for coding standards.
  38.  
  39. Obviously anyone who asks this question on comp.lang.c++ wants to be trained so
  40. they DON'T run off on their own ignorance, but nonetheless the answers tend to
  41. generate more heat than light.
  42.  
  43. ==============================================================================
  44.  
  45. Q88: Are coding standards necessary?  Are they sufficient?
  46.  
  47. Coding standards do not make non OO programmers into OO programmers; only
  48. training and experience do that.  If coding standards have merit, it is that
  49. they discourage the petty fragmentation that occurs when large organizations
  50. coordinate the activities of diverse groups of programmers.
  51.  
  52. But you really want more than a coding standard.  The structure provided by
  53. coding standards gives neophytes one less degree of freedom to worry about,
  54. however pragmatics go well beyond pretty-printing standards.  Organizations
  55. need a consistent PHILOSOPHY of design and implementation.  E.g., strong or
  56. weak typing?  references or ptrs in interfaces?  stream I/O or stdio?  should
  57. C++ code call our C?  vise versa?  how should ABCs be used?  should inheritance
  58. be used as an implementation technique or as a specification technique?  what
  59. testing strategy should be employed?  inspection strategy?  should interfaces
  60. uniformly have a "get" and/or "set" method for each data member?  should
  61. interfaces be designed from the outside-in or the inside-out?  should errors be
  62. handled by try/catch/throw or return codes?  etc.
  63.  
  64. What is needed is a "pseudo standard" for detailed DESIGN.  I recommend a
  65. three-pronged approach to achieving this standardization: training, mentoring,
  66. and libraries.  Training provides "intense instruction," mentoring allows OO to
  67. be caught rather than just taught, and a high quality C++ class library
  68. provides "long term instruction."  There is a thriving commercial market for
  69. all three kinds of "training."  Advice by organizations who have been through
  70. the mill is consistent: Buy, Don't Build.  Buy libraries, buy training, buy
  71. tools, buy consulting.  Companies who have attempted to become a self-taught
  72. tool-shop as well as an application/system shop have found success difficult.
  73.  
  74. Few argue that coding standards are "ideal," or even "good," however they are
  75. necessary in the kind of organizations/situations described above.
  76.  
  77. The following FAQs provide some basic guidance in conventions and styles.
  78.  
  79. ==============================================================================
  80.  
  81. Q89: Should our organization determine coding standards from our C
  82.    experience?
  83.  
  84. No!
  85.  
  86. No matter how vast your C experience, no matter how advanced your C expertise,
  87. being a good C programmer does not make you a good C++ programmer.  Converting
  88. from C to C++ is more than just learning the syntax and semantics of the "++"
  89. part of C++.  Organizations who want the promise of OOP, but who fail to put
  90. the "OO" into OOP, are fooling themselves; the balance sheet will show their
  91. folly.
  92.  
  93. C++ coding standards should be tempered by C++ experts.  Asking comp.lang.c++
  94. is a start (but don't use the term "coding standard" in the question; instead
  95. simply say, "what are the pros and cons of this technique?").  Seek out experts
  96. who can help guide you away from pitfalls.  Get training.  Buy libraries and
  97. see if "good" libraries pass your coding standards.  Do NOT set standards by
  98. yourself unless you have considerable experience in C++.  Having no standard is
  99. better than having a bad standard, since improper "official" positions "harden"
  100. bad brain traces.  There is a thriving market for both C++ training and
  101. libraries from which to pool expertise.
  102.  
  103. One more thing: whenever something is in demand, the potential for charlatans
  104. increases.  Look before you leap.  Also ask for student-reviews from past
  105. companies, since not even expertise makes someone a good communicator.
  106. Finally, select a practitioner who can teach, not a full time teacher who has a
  107. passing knowledge of the language/paradigm.
  108.  
  109. ==============================================================================
  110.  
  111. Q90: Should I declare locals in the middle of a fn or at the top?
  112.  
  113. Declare near first use.
  114.  
  115. An object is initialized (constructed) the moment it is declared.  If you don't
  116. have enough information to initialize an object until half way down the fn, you
  117. can either initialize it to an "empty" value at the top then "assign" it later,
  118. or initialize it correctly half way down the fn.  It's cheaper (in runtime
  119. performance) to get it right the first time than to build it once, tear it
  120. down, and build it again.  Simple examples show a factor of 350% speed hit for
  121. simple classes like "String".  Your mileage may vary; surely the overall system
  122. degradation will be less that 300+%, but there WILL be degradation.
  123. UNNECESSARY degradation.
  124.  
  125. A common retort to the above is: "we"ll provide "set" methods for every datum
  126. in our objects, so the cost of construction will be spread out."  This is worse
  127. than the performance overhead, since now you're introducing a maintenance
  128. nightmare.  Providing "set" methods for every datum is tantamount to public
  129. data: you've exposed your implementation technique to the world.  The only
  130. thing you've hidden is the physical NAMES of your member objects, but the fact
  131. that you're using a List and a String and a float (for example) is open for all
  132. to see.  Maintenance generally consumes far more resources than run-time CPU.
  133.  
  134. Locals should be declared near their first use.  Sorry that this isn't familiar
  135. to C experts, but "new" doesn't necessarily mean "bad."
  136.  
  137. ==============================================================================
  138.  
  139. Q91: What source-file-name convention is best? "foo.C"? "foo.cc"? "foo.cpp"?
  140.  
  141. If you already have a convention, use it.  If not, consult your compiler to see
  142. what the compiler expects.  Typical answers are: ".C", ".cc", ".cpp", or
  143. ".cxx" (naturally the ".C" extension assumes a case-sensitive file system to
  144. distinguish ".C" from ".c").
  145.  
  146. At Paradigm Shift, Inc., we have used both ".cpp" for our C++ source files, and
  147. we have also used ".C".  In the latter case, we supplly the compiler option
  148. forces .c files to be treated as C++ source files ("-Tdp" for IBM CSet++,
  149. "-cpp" for Zortech C++, "-P" for Borland C++, etc.) when porting to
  150. case-insensitive file systems.  None of these approaches have any striking
  151. technical superiority to the others; we generally use whichever technique is
  152. preferred by our customer (again, these issues are dominated by business
  153. considerations, not by technical considerations).
  154.  
  155. ==============================================================================
  156.  
  157. Q92: What header-file-name convention is best? "foo.H"? "foo.hh"? "foo.hpp"?
  158.  
  159. If you already have a convention, use it.  If not, and if you don't need your
  160. editor to distinguish between C and C++ files, simply use ".h".  Otherwise use
  161. whatever the editor wants, such as ".H", ".hh", or ".hpp".
  162.  
  163. At Paradigm Shift, Inc., we use ".h" for both C and C++ source files (then
  164. again, we don't create many straight C header files).
  165.  
  166. ==============================================================================
  167.  
  168. Q93: Are there any lint-like guidelines for C++?
  169.  
  170. Yes, there are some practices which are generally considered dangerous.
  171. However none of these are universally "bad," since situations arise when
  172. even the worst of these is needed:
  173.  * a class "Fred"s assignment operator should return "*this" as an "Fred&"
  174.    (allows chaining of assignments)
  175.  * a class with any virtual fns ought to have a virtual destructor
  176.  * a class with any of {destructor, assignment operator, copy constructor}
  177.    generally needs all 3
  178.  * a class "Fred"s copy constructor and assignment operator should have "const"
  179.    in the parameter: respectively "Fred::Fred(const Fred&)" and
  180.    "Fred& Fred::operator=(const Fred&)".
  181.  * always use initialization lists for class sub-objects rather than assignment
  182.    the performance difference for user-defined classes can be substantial (3x!)
  183.  * many assignment operators should start by testing if "we" are "them"; e.g.,
  184.     Fred& Fred::operator= (const Fred& fred)
  185.     {
  186.       if (this == &fred) return *this;
  187.       //...normal assignment duties...
  188.       return *this;
  189.     }
  190.    sometimes there is no need to check, but these situations generally
  191.    correspond to when there's no need for an explicit user-specified assignment
  192.    op (as opposed to a compiler-synthesized assignment-op).
  193.  * in classes that define both "+=," "+" and "=," "a+=b" and "a=a+b" should
  194.    generally do the same thing; ditto for the other identities of builtin types
  195.    (e.g., a+=1 and ++a; p[i] and *(p+i); etc).  This can be enforced by writing
  196.    the binary ops using the "op=" forms; e.g.,
  197.     Fred operator+ (const Fred& a, const Fred& b)
  198.     {
  199.       Fred ans = a;
  200.       ans += b;
  201.       return ans;
  202.     }
  203.    This way the "constructive" binary ops don't even need to be friends.  But
  204.    it is sometimes possible to more efficiently implement common ops (e.g., if
  205.    class "Fred" is actually "String," and "+=" has to reallocate/copy string
  206.    memory, it may be better to know the eventual length from the beginning).
  207.  
  208. ==============================================================================
  209. SECTION 15: Keys for Smalltalk programmers to learn C++
  210. ==============================================================================
  211.  
  212. Q94: Why does C++'s FAQ have a section on Smalltalk? Is this
  213.    Smalltalk-bashing?
  214.  
  215. The two "major" OOPLs in the world are C++ and Smalltalk.  Due to its
  216. popularity as the OOPL with the second largest user pool, many new C++
  217. programmers come from a Smalltalk background.  This section answers the
  218. questions:
  219.  * what's different about the two languages
  220.  * what must a Smalltalk-turned-C++ programmer know to master C++
  221.  
  222. This section does *!*NOT*!* attempt to answer the questions:
  223.  * which language is "better"?
  224.  * why is Smalltalk "bad"?
  225.  * why is C++ "bad"?
  226.  
  227. Nor is it an open invitation for some Smalltalk terrorist to slash my tires
  228. while I sleep (on those rare occasions when I have time to rest these days :-).
  229.  
  230. ==============================================================================
  231.  
  232. Q95: What's the difference between C++ and Smalltalk?
  233.  
  234. The most important differences are:
  235.  
  236.  * static typing vs dynamic typing?
  237.  * must inheritance be used for subtyping only?
  238.  * value vs reference semantics?
  239.  
  240. The first two differences are illuminated in the remainder of this section; the
  241. third point is the subject of the section that follows.
  242.  
  243. If you're a Smalltalk programmer who wants to learn C++, you'd be very wise to
  244. study the next three FAQs carefully.
  245.  
  246. ==============================================================================
  247.  
  248. Q96: What is "static typing", and how is it similar/dissimilar to Smalltalk?
  249.  
  250. Static typing says the compiler checks the type-safety of every operation
  251. STATICALLY (at compile-time), rather than to generate code which will check
  252. things at run-time.  For example, with static typing, the signature matching of
  253. fn arguments is checked, and an improper match is flagged as an error by the
  254. COMPILER, not at run-time.
  255.  
  256. In OO code, the most common "typing mismatch" is invoking a member function
  257. against an object which isn't prepared to handle the operation.  E.g., if class
  258. "Fred" has member fn "f()" but not "g()", and "fred" is an instance of class
  259. "Fred", then "fred.f()" is legal and "fred.g()" is illegal.  C++ (statically
  260. typed) catches the error at compile time, and Smalltalk (dynamically typed)
  261. catches the error at run-time.  (Technically speaking, C++ is like Pascal
  262. --PSEUDO statically typed-- since ptr casts and unions can be used to violate
  263. the typing system; which reminds me: only use ptr casts and unions as often as
  264. you use "goto"s).
  265.  
  266. ==============================================================================
  267.  
  268. Q97: Which is a better fit for C++: "static typing" or "dynamic typing"?
  269.  
  270. If you want to use C++ most effectively, use it as a statically typed language.
  271.  
  272. C++ is flexible enough that you can (via ptr casts, unions, and #defines) make
  273. it "look" like Smalltalk.  But don't.  Which reminds me: try to avoid #define.
  274.  
  275. There are places where ptr casts and unions are necessary and even wholesome,
  276. but they should be used carefully and sparingly.  A ptr cast tells the compiler
  277. to believe you.  An incorrect ptr cast might corrupt your heap, scribble into
  278. memory owned by other objects, call nonexistent methods, and cause general
  279. failures.  It's not a pretty sight.  If you avoid these and related constructs,
  280. you can make your C++ code both safer and faster, since anything that can be
  281. checked at compile time is something that doesn't have to be done at run-time.
  282.  
  283. If you're interested in using a pointer cast, use the new style pointer casts.
  284. The most common example of these is to change old-style pointer casts such as
  285. '(X*)p' into new-style dynamic casts such as 'dynamic_cast<X*>(p)' (where 'p'
  286. is a pointer and 'X' is a type).  In addition to dynamic_cast, there is
  287. static_cast and const_cast, but dynamic_cast is the one that simulates most of
  288. the advantages of dynamic typing (the other is the 'typeid()' construct; for
  289. example, 'typeid(*p).name()' will return the name of the type of '*p').
  290.  
  291. ==============================================================================
  292.  
  293. Q98: How can you tell if you have a dynamically typed C++ class library?
  294.  
  295. Hint #1: when everything is derived from a single root class, usually "Object."
  296. Hint #2: when the container classes (List, Stack, Set, etc) are non-templates.
  297. Hint #3: when the container classes (List, Stack, Set, etc) insert/extract
  298. elements as pointers to "Object" (you can put an Apple into such a container,
  299. but when you get it out, the compiler knows only that it is derived from
  300. Object, so you have to use a pointer cast to convert it back to an Apple*; and
  301. you better pray a lot that it really IS an Apple, cause your blood is on your
  302. own head).
  303.  
  304. You can make the pointer cast "safe" by using "dynamic_cast", but this dynamic
  305. testing is just that: dynamic.  This coding style is the essence of dynamic
  306. typing in C++.  You call a function that says "convert this Object into an
  307. Apple or give me NULL if its not an Apple," and you've got dynamic typing: you
  308. don't know what will happen until run-time.
  309.  
  310. When you use with templates to implement your containers, the C++ compiler can
  311. statically validate 99% of an application's typing information (the figure
  312. "99%" is apocryphal; some claim they always get 100%, those who need
  313. persistence get something less than 100% static type checking).  The point is:
  314. C++ gets genericity from templates, not from inheritance.
  315.  
  316. ==============================================================================
  317.  
  318. Q99: How do you use inheritance in C++, and is that different from Smalltalk?
  319.  
  320. Some people believe that the purpose of inheritance is code reuse.  In C++,
  321. this is wrong.  Stated plainly, "inheritance is not 'for' code reuse."
  322.  
  323. The purpose of inheritance in C++ is to express interface compliance
  324. (subtyping), not to get code reuse.  In C++, code reuse usually comes via
  325. composition rather than via inheritance.  In other words, inheritance is mainly
  326. a specification technique rather than an implementation technique.
  327.  
  328. This is a major difference with Smalltalk, where there is only one form of
  329. inheritance (C++ provides "private" inheritance to mean "share the code but
  330. don't conform to the interface", and "public" inheritance to mean "kind-of").
  331. The Smalltalk language proper (as opposed to coding practice) allows you to
  332. have the EFFECT of "hiding" an inherited method by providing an override that
  333. calls the "does not understand" method.  Furthermore Smalltalk allows a
  334. conceptual "is-a" relationship to exist APART from the subclassing hierarchy
  335. (subtypes don't have to be subclasses; e.g., you can make something that is-a
  336. Stack yet doesn't inherit from class Stack).
  337.  
  338. In contrast, C++ is more restrictive about inheritance: there's no way to make
  339. a "conceptual is-a" relationship without using inheritance (the C++ work-around
  340. is to separate interface from implementation via ABCs).  The C++ compiler
  341. exploits the added semantic information associated with public inheritance to
  342. provide static typing.
  343.  
  344. ==============================================================================
  345.  
  346. Q100: What are the practical consequences of diffs in Smalltalk/C++
  347.    inheritance?
  348.  
  349. Smalltalk lets you make a subtype that isn't a subclass, and allows you to make
  350. a subclass that isn't a subtype.  This allows Smalltalk programmers to be very
  351. carefree in putting data (bits, representation, data structure) into a class
  352. (e.g., you might put a linked list into a Stack class).  After all, if someone
  353. wants an array-based-Stack, they don't have to inherit from Stack; they could
  354. inherit such a class from Array if desired, even though an ArrayBasedStack is
  355. NOT a kind-of Array!
  356.  
  357. In C++, you can't be nearly as carefree.  Only mechanism (method code), but not
  358. representation (data bits) can be overridden in subclasses.  Therefore you're
  359. usually better off NOT putting the data structure in a class.  This leads to a
  360. stronger reliance on Abstract Base Classes (ABCs).
  361.  
  362. I like to think of the difference between an ATV and a Maseratti.  An ATV (all
  363. terrain vehicle) is more fun, since you can "play around" by driving through
  364. fields, streams, sidewalks, and the like.  A Maseratti, on the other hand, gets
  365. you there faster, but it forces you to stay on the road.  My advice to C++
  366. programmers is simple: stay on the road.  Even if you're one of those people
  367. who like the "expressive freedom" to drive through the bushes, don't do it in
  368. C++; it's not a good fit.
  369.  
  370. ==============================================================================
  371.  
  372. Q101: Do you need to learn a "pure" OOPL before you learn C++?
  373.  
  374. No (in fact, doing so might actually hurt you).
  375.  
  376. (Note that Smalltalk is a "pure" OOPL, and C++ is a "hybrid" OOPL).  Before
  377. reading this, please read the previous FAQs on the difference between C++ and
  378. Smalltalk.
  379.  
  380. The "purity" of the OOPL doesn't make the transition to C++ any easier.  In
  381. fact, the typical use of dynamic typing and non-subtyping inheritance can make
  382. it even harder for Smalltalk programmers to learn C++.  Paradigm Shift, Inc.,
  383. has taught OO technology to literally thousands of people, and we have noticed
  384. that people who want to learn C++ from a Smalltalk background usually have just
  385. as hard a time as those who've never seen inheritance before.  In fact, those
  386. with extensive experience with a dynamically typed OOPL (usually but not always
  387. Smalltalk) might even have a HARDER time, since it's harder to UNLEARN habits
  388. than it is to learn the statically typed way from the beginning.
  389.  
  390. ==============================================================================
  391.  
  392. Q102: What is the NIHCL?  Where can I get it?
  393.  
  394. NIHCL stands for "national-institute-of-health's-class-library."
  395. it can be acquired via anonymous ftp from [128.231.128.7]
  396. in the file pub/NIHCL/nihcl-3.0.tar.Z
  397.  
  398. NIHCL (some people pronounce it "N-I-H-C-L," others pronounce it like "nickel")
  399. is a C++ translation of the Smalltalk class library.  There are some ways where
  400. NIHCL's use of dynamic typing helps (e.g., persistent objects).  There are also
  401. places where its use of dynamic typing creates tension with the static typing
  402. of the C++ language.
  403.  
  404. See previous FAQs on Smalltalk for more.
  405.  
  406. ==============================================================================
  407. SECTION 16: Reference and value semantics
  408. ==============================================================================
  409.  
  410. Q103: What is value and/or reference semantics, and which is best in C++?
  411.  
  412. With reference semantics, assignment is a pointer-copy (i.e., a REFERENCE).
  413. Value (or "copy") semantics mean assignment copies the value, not just the
  414. pointer.  C++ gives you the choice: use the assignment operator to copy the
  415. value (copy/value semantics), or use a ptr-copy to copy a pointer (reference
  416. semantics).  C++ allows you to override the assignment operator to do anything
  417. your heart desires, however the default (and most common) choice is to copy the
  418. VALUE.
  419.  
  420. Pros of reference semantics: flexibility and dynamic binding (you get dynamic
  421. binding in C++ only when you pass by ptr or pass by ref, not when you pass by
  422. value).
  423.  
  424. Pros of value semantics: speed.  "Speed" seems like an odd benefit to for a
  425. feature that requires an object (vs a ptr) to be copied, but the fact of the
  426. matter is that one usually accesses an object more than one copies the object,
  427. so the cost of the occasional copies is (usually) more than offset by the
  428. benefit of having an actual object rather than a ptr to an object.
  429.  
  430. There are three cases when you have an actual object as opposed to a pointer to
  431. an object: local vars, global/static vars, and fully contained member objects
  432. in a class.  The most important of these is the last ("composition").
  433.  
  434. More info about copy-vs-reference semantics is given in the next FAQs.  Please
  435. read them all to get a balanced perspective.  The first few have intentionally
  436. been slanted toward value semantics, so if you only read the first few of the
  437. following FAQs, you'll get a warped perspective.
  438.  
  439. Assignment has other issues (e.g., shallow vs deep copy) which are not covered
  440. here.
  441.  
  442. ==============================================================================
  443.  
  444. Q104: What is "virtual data," and how-can / why-would I use it in C++?
  445.  
  446. Virtual data allows a derived class to change the exact class of a base class's
  447. member object.  Virtual data isn't strictly "supported" by C++, however it
  448. can be simulated in C++.  It ain't pretty, but it works.
  449.  
  450. To simulate virtual data in C++, the base class must have a pointer to the
  451. member object, and the derived class must provide a "new" object to be pointed
  452. to by the base class's pointer.  The base class would also have one or more
  453. normal constructors that provide their own referrent (again via "new"), and the
  454. base class's destructor would "delete" the referent.
  455.  
  456. For example, class "Stack" might have an Array member object (using a pointer),
  457. and derived class "StretchableStack" might override the base class member data
  458. from "Array" to "StretchableArray".  For this to work, StretchableArray would
  459. have to inherit from Array, so Stack would have an "Array*".  Stack's normal
  460. constructors would initialize this "Array*" with a "new Array", but Stack would
  461. also have a (possibly "protected:") constructor that would accept an "Array*"
  462. from a derived class.  StretchableArray's constructor would provide a "new
  463. StretchableArray" to this special constructor.
  464.  
  465. Pros:
  466.  * Easier implementation of StretchableStack (most of the code is inherited).
  467.  * Users can pass a StretchableStack as a kind-of Stack.
  468.  
  469. Cons:
  470.  * Adds an extra layer of indirection to access the Array.
  471.  * Adds some extra freestore allocation overhead (both new and delete).
  472.  * Adds some extra dynamic binding overhead (reason given in next FAQ).
  473.  
  474. In other words, we succeeded at making OUR job easier as the implementor of
  475. StretchableStack, but all our users pay for it.  Unfortunately the extra
  476. overhead was imposed on both users of StretchableStack AND on users of Stack.
  477.  
  478. See the FAQ after the next to find out how much the users "pay."  Also: PLEASE
  479. read the few FAQs that follow the next one too (YOU WILL NOT GET A BALANCED
  480. PERSPECTIVE WITHOUT THE OTHERS).
  481.  
  482. ==============================================================================
  483.  
  484. Q105: What's the difference between virtual data and dynamic data?
  485.  
  486. The easiest way to see the distinction is by an analogy with "virtual fns":
  487. A virtual member fn means the declaration (signature) must stay the same in
  488. subclasses, but the defn (body) can be overridden.  The overriddenness of an
  489. inherited member fn is a static property of the subclass; it doesn't change
  490. dynamically throughout the life of any particular object, nor is it possible
  491. for distinct objects of the subclass to have distinct defns of the member fn.
  492.  
  493. Now go back and re-read the previous paragraph, but make these substitutions:
  494.  * "member fn" --> "member object"
  495.  * "signature" --> "type"
  496.  * "body"      --> "exact class'
  497. After this, you'll have a working definition of virtual data.
  498.  
  499. Another way to look at this is to distinguish "per-object" member functions
  500. from "dynamic" member functions.  A "per-object" member fn is a member fn that
  501. is potentially different in any given instance of an object, and could be
  502. implemented by burying a function ptr in the object; this pointer could be
  503. "const", since the pointer will never be changed throughout the object's life.
  504. A "dynamic" member fn is a member fn that will change dynamically over time;
  505. this could also be implemented by a function ptr, but the fn ptr would not be
  506. const.
  507.  
  508. Extending the analogy, this gives us three distinct concepts for data members:
  509.  * virtual data: the defn ("class") of the member object is overridable in
  510.    subclasses provided its declaration ("type") remains the same, and this
  511.    overriddenness is a static property of the subclass.
  512.  * per-object-data: any given object of a class can instantiate a different
  513.    conformal (same type) member object upon initialization (usually a "wrapper"
  514.    object), and the exact class of the member object is a static property of
  515.    the object that wraps it.
  516.  * dynamic-data: the member object's exact class can change dynamically over
  517.    time.
  518.  
  519. The reason they all look so much the same is that none of this is "supported"
  520. in C++.  It's all merely "allowed," and in this case, the mechanism for faking
  521. each of these is the same: a ptr to a (probably abstract) base class.  In a
  522. language that made these "first class" abstraction mechanisms, the difference
  523. would be more striking, since they'd each have a different syntactic variant.
  524.  
  525. ==============================================================================
  526.  
  527. Q106: Should I normally use pointers to freestore allocated objects for my
  528.    data members, or should I use "composition"?
  529.  
  530. Composition.
  531.  
  532. Your member objects should normally be "contained" in the composite object (but
  533. not always; "wrapper" objects are a good example of where you want a ptr/ref;
  534. also the N-to-1-uses-a relationship needs something like a ptr/ref).
  535.  
  536. There are three reasons why fully contained member objects ("composition") has
  537. better performance than ptrs to freestore-allocated member objects:
  538.  
  539.  * Extra layer to indirection every time you need to access the member object.
  540.  * Extra freestore allocations ("new" in constructor, "delete" in destructor).
  541.  * Extra dynamic binding (reason given below).
  542.  
  543. ==============================================================================
  544.  
  545. Q107: What are relative costs of the 3 performance hits associated with
  546.    allocating member objects from the freestore?
  547.  
  548. The three performance hits are enumerated in the previous FAQ:
  549.  * By itself, an extra layer of indirection is small potatoes.
  550.  * Freestore allocations can be a performance issue (the performance of the
  551.    typical implementation of malloc degrades when there are many allocations;
  552.    OO s/w can easily become "freestore bound" unless you're careful).
  553.  * The extra dynamic binding comes from having a ptr rather than an object.
  554.    Whenever the C++ compiler can know an object's EXACT class, virtual fn
  555.    calls can be STATICALLY bound, which allows inlining.  Inlining allows
  556.    zillions (would you believe half a dozen :-) optimization opportunities
  557.    such as procedural integration, register lifetime issues, etc.  The C++
  558.    compiler can know an object's exact class in three circumstances: local
  559.    variables, global/static variables, and fully-contained member objects.
  560.  
  561. Thus fully-contained member objects allow significant optimizations that
  562. wouldn't be possible under the "member objects-by-ptr" approach.  This is the
  563. main reason that languages which enforce reference-semantics have "inherent"
  564. performance challenges.
  565.  
  566. NOTE: PLEASE READ THE NEXT THREE FAQs TO GET A BALANCED PERSPECTIVE!
  567.  
  568. ==============================================================================
  569.  
  570. Q108: Are "inline virtual" member fns ever actually "inlined"?
  571.  
  572. Yes but...
  573.  
  574. A virtual call via a ptr or ref is always resolved dynamically, which can never
  575. be inlined.  Reason: the compiler can't know which actual code to call until
  576. run-time (i.e., dynamically), since the code may be from a derived class that
  577. was created after the caller was compiled.
  578.  
  579. Therefore the only time an inline virtual call can be inlined is when the
  580. compiler knows the "exact class" of the object which is the target of the
  581. virtual function call.  This can happen only when the compiler has an actual
  582. object rather than a pointer or reference to an object.  I.e., either with a
  583. local object, a global/static object, or a fully contained object inside a
  584. composite.
  585.  
  586. Note that the difference between inlining and non-inlining is normally MUCH
  587. more significant than the difference between a regular fn call and a virtual fn
  588. call.  For example, the difference between a regular fn call and a virtual fn
  589. call is often just two extra memory references, but the difference between an
  590. inline function and a non-inline function can be as much as an order of
  591. magnitude (for zillions of calls to insignificant member fns, loss of inlining
  592. virtual fns can result in 25X speed degradation!  [Doug Lea, "Customization in
  593. C++," proc Usenix C++ 1990]).
  594.  
  595. A practical consequence of this insight: don't get bogged down in the endless
  596. debates (or sales tactics!) of compiler/language vendors who compare the cost
  597. of a virtual function call on their language/compiler with the same on another
  598. language/compiler.  Such comparisons are largely meaningless when compared with
  599. the ability of the language/compiler to "inline expand" member function calls.
  600. I.e., many language implementation vendors make a big stink about how good
  601. their dispatch strategy is, but if these implementations don't INLINE method
  602. calls, the overall system performance would be poor, since it is inlining --NOT
  603. dispatching-- that has the greatest performance impact.
  604.  
  605. NOTE: PLEASE READ THE NEXT TWO FAQs TO SEE THE OTHER SIDE OF THIS COIN!
  606.  
  607. ==============================================================================
  608.  
  609. Q109: Sounds like I should never use reference semantics, right?
  610.  
  611. Wrong.
  612.  
  613. Reference semantics are A Good Thing.  We can't live without pointers.  We just
  614. don't want our s/w to be One Gigantic Rats Nest Of Pointers.  In C++, you can
  615. pick and choose where you want reference semantics (ptrs/refs) and where you'd
  616. like value semantics (where objects physically contain other objects etc).  In
  617. a large system, there should be a balance.  However if you implement absolutely
  618. EVERYTHING as a pointer, you'll get enormous speed hits.
  619.  
  620. Objects near the problem skin are larger than higher level objects.  The
  621. IDENTITY of these "problem space" abstractions is usually more important than
  622. their "value."  Thus reference semantics should be used for problem-space
  623. objects.
  624.  
  625. Note that these problem space objects are normally at a higher level of
  626. abstraction than the solution space objects, so the problem space objects
  627. normally have a relatively lower frequency of interaction.  Therefore C++ gives
  628. us an IDEAL situation: we choose reference semantics for objects that need
  629. unique identity or that are too large to copy, and we can choose value
  630. semantics for the others.  Thus the highest frequency objects will end up with
  631. value semantics, since we install flexibility where it doesn't hurt us (only),
  632. and we install performance where we need it most!
  633.  
  634. These are some of the many issues the come into play with real OO design.
  635. OO/C++ mastery takes time and high quality training.  If you want a powerful
  636. tool, you've got to invest.
  637.  
  638.            <<<<DON'T STOP NOW!  READ THE NEXT FAQ TOO!!>>>>
  639.  
  640. ==============================================================================
  641.  
  642. Q110: Does the poor performance of ref semantics mean I should pass-by-value?
  643.  
  644. Nope.
  645.  
  646. The previous FAQ were talking about MEMBER OBJECTS, not parameters.  Generally,
  647. objects that are part of an inheritance hierarchy should be passed by ref or by
  648. ptr, NOT by value, since only then do you get the (desired) dynamic binding
  649. (pass-by-value doesn't mix with inheritance, since larger subclass objects get
  650. "sliced" when passed by value as a base class object).
  651.  
  652. Unless compelling reasons are given to the contrary, member objects should be
  653. by value and parameters should be by reference.  The discussion in the previous
  654. few FAQs indicates some of the "compelling reasons" for when member objects
  655. should be by reference.
  656.  
  657. --
  658. Paradigm Shift, Inc. / P.O. Box 5108 / Potsdam, NY  13676
  659. Technology consulting services
  660. cline@parashift.com / Voice: 315-353-6100 / FAX: 315-353-6110
  661.